//go:build !notmpfiles
// +build !notmpfiles

// Package collector 包含所有用于收集和导出系统指标的单独收集器。
package collector

import (
	"fmt"
	"log/slog"
	"os"
	"regexp"
	"strconv"
)

// ParseStorcliLog 解析 storcli 日志文件并提取磁盘信息
func ParseStorcliLog(filename string, logger *slog.Logger) ([]DiskInfo, error) {
	// 读取文件数据
	data, err := os.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("读取 storcli 日志失败: %w", err)
	}

	content := string(data)

	// 使用 Info 级别确保日志输出
	logger.Info("开始解析 StorCLI 日志", "文件大小", len(content))

	// 使用正则表达式查找驱动器块 - 匹配每个磁盘的完整信息部分
	// 使用自定义分隔方式处理，避免使用前瞻断言
	driveSections := extractDriveSections(content)

	logger.Info("找到驱动器部分数量", "数量", len(driveSections))

	disks := make([]DiskInfo, 0)

	// 遍历所有匹配的驱动器
	for i, section := range driveSections {
		logger.Info("处理驱动器部分", "索引", i, "内容长度", len(section))

		// 提取驱动器路径作为设备ID
		deviceID := "Unknown"
		deviceIDRegex := regexp.MustCompile(`Drive (/c\d+/e\d+/s\d+)`)
		deviceIDMatch := deviceIDRegex.FindStringSubmatch(section)
		if len(deviceIDMatch) >= 2 {
			deviceID = deviceIDMatch[1]
		}

		// 添加更多上下文信息
		preview := section
		if len(section) > 100 {
			preview = section[:100]
		}
		logger.Info("提取到设备ID", "设备ID", deviceID, "部分预览", preview)

		// 创建磁盘信息结构
		disk := DiskInfo{
			DeviceID:    deviceID,      // 保持原始格式
			Controller:  "controller0", // 在实际实现中，您将从日志中提取此信息
			ErrorCounts: make(map[string]int),
		}

		// 查找错误计数器 - 使用更宽松的匹配模式
		mediaErrorRegex := regexp.MustCompile(`Media Error Count\s*=\s*(\d+)`)
		otherErrorRegex := regexp.MustCompile(`Other Error Count\s*=\s*(\d+)`)
		predictiveFailureRegex := regexp.MustCompile(`Predictive Failure Count\s*=\s*(\d+)`)
		shieldCounterRegex := regexp.MustCompile(`Shield Counter\s*=\s*(\d+)`)

		// 提取 Media Error Count
		if mediaErrMatch := mediaErrorRegex.FindStringSubmatch(section); len(mediaErrMatch) >= 2 {
			count, _ := strconv.Atoi(mediaErrMatch[1])
			disk.ErrorCounts["Media Error Count"] = count
			logger.Info("提取 Media Error Count", " 计数", count)
		} else {
			preview := section
			if len(section) > 200 {
				preview = section[:200]
			}
			logger.Info("未找到 Media Error Count", "部分预览", preview)
		}

		// 提取 Other Error Count
		if otherErrMatch := otherErrorRegex.FindStringSubmatch(section); len(otherErrMatch) >= 2 {
			count, _ := strconv.Atoi(otherErrMatch[1])
			disk.ErrorCounts["Other Error Count"] = count
			logger.Info("提取 Other Error Count", " 计数", count)
		} else {
			preview := section
			if len(section) > 200 {
				preview = section[:200]
			}
			logger.Info("未找到 Other Error Count", "部分预览", preview)
		}

		// 提取 Predictive Failure Count
		if predFailMatch := predictiveFailureRegex.FindStringSubmatch(section); len(predFailMatch) >= 2 {
			count, _ := strconv.Atoi(predFailMatch[1])
			disk.ErrorCounts["Predictive Failure Count"] = count
			logger.Info("提取 Predictive Failure Count", " 计数", count)
		} else {
			preview := section
			if len(section) > 200 {
				preview = section[:200]
			}
			logger.Info("未找到 Predictive Failure Count", "部分预览", preview)
		}

		// 提取 Shield Counter
		if shieldCounterMatch := shieldCounterRegex.FindStringSubmatch(section); len(shieldCounterMatch) >= 2 {
			count, _ := strconv.Atoi(shieldCounterMatch[1])
			disk.ErrorCounts["Shield Counter"] = count
			logger.Info("提取 Shield Counter", "计数", count)
		} else {
			preview := section
			if len(section) > 200 {
				preview = section[:200]
			}
			logger.Info("未找到 Shield Counter", "部分预览", preview)
		}

		disks = append(disks, disk)
		logger.Info("添加磁盘信息", "设备ID", disk.DeviceID, "错误计数", disk.ErrorCounts)
	}

	logger.Info("完成 StorCLI 日志解析", "磁盘数量", len(disks))

	// 返回磁盘信息和空错误
	return disks, nil
}

// ParseStorcliLogicDiskLog 解析 storcli 日志文件并提取逻辑磁盘信息
func ParseStorcliLogicDiskLog(filename string, logger *slog.Logger) ([]LogicDiskInfo, error) {
	// 读取文件数据
	data, err := os.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("读取 storcli 逻辑磁盘日志失败: %w", err)
	}

	content := string(data)

	// 使用 Info 级别确保日志输出
	logger.Info("开始解析 StorCLI 逻辑磁盘日志", "文件大小", len(content))

	// 使用正则表达式查找虚拟驱动器(VD)块的起始位置
	vdStartRegex := regexp.MustCompile(`/c\d+/v\d+\s*:`)
	vdPositions := vdStartRegex.FindAllStringIndex(content, -1)

	if len(vdPositions) == 0 {
		logger.Info("未找到虚拟驱动器部分")
		return []LogicDiskInfo{}, nil
	}

	logger.Info("找到虚拟驱动器部分数量", "数量", len(vdPositions))

	disks := make([]LogicDiskInfo, 0)

	// 遍历所有匹配的虚拟驱动器
	for i := 0; i < len(vdPositions); i++ {
		// 确定虚拟驱动器块的范围
		start := vdPositions[i][0]
		end := len(content)
		if i+1 < len(vdPositions) {
			end = vdPositions[i+1][0]
		}

		// 提取虚拟驱动器块内容
		vdBlock := content[start:end]

		// 创建逻辑磁盘信息结构
		disk := LogicDiskInfo{
			Controller: "controller0",
			Info:       make(map[string]string),
		}

		// 提取设备ID
		deviceIDRegex := regexp.MustCompile(`(/c\d+/v\d+)`)
		if deviceIDMatch := deviceIDRegex.FindStringSubmatch(vdBlock); len(deviceIDMatch) >= 2 {
			disk.DeviceID = deviceIDMatch[1]
		}

		// 提取 RAID 级别、状态、大小等信息
		// 匹配类似这样的行: 0/0   RAID1 Optl  RW     Yes     RWTD  -   ON  3.637 TB
		infoRegex := regexp.MustCompile(`(\d+/\d+)\s+(RAID\d+)\s+(\w+)\s+\w+\s+\w+\s+\w+\s+\S*\s+\S*\s+([0-9.]+\s+[MGTP]B)`)
		if infoMatch := infoRegex.FindStringSubmatch(vdBlock); len(infoMatch) >= 5 {
			disk.RaidLevel = infoMatch[2]
			disk.State = mapStorcliState(infoMatch[3])
			disk.Size = infoMatch[4]
		}

		// 查找物理磁盘数量
		// 直接使用 "Number of Drives Per Span" 字段
		drivesPerSpanRegex := regexp.MustCompile(`Number of Drives Per Span\s*=\s*(\d+)`)
		if drivesPerSpanMatch := drivesPerSpanRegex.FindStringSubmatch(vdBlock); len(drivesPerSpanMatch) >= 2 {
			drivesPerSpan, _ := strconv.Atoi(drivesPerSpanMatch[1])
			disk.NumberOfDrives = drivesPerSpan
		}

		// 如果成功提取了设备ID，则添加到结果中
		if disk.DeviceID != "" {
			disks = append(disks, disk)
			logger.Info("添加逻辑磁盘信息",
				"设备ID", disk.DeviceID,
				"RAID级别", disk.RaidLevel,
				"状态", disk.State,
				"大小", disk.Size,
				"磁盘数量", disk.NumberOfDrives)
		}
	}

	logger.Info("完成 StorCLI 逻辑磁盘日志解析", "磁盘数量", len(disks))

	return disks, nil
}

// mapStorcliState 映射 storcli 状态到通用状态
func mapStorcliState(state string) string {
	stateMap := map[string]string{
		"Optl": "Optimal",
		"Dgrd": "Degraded",
		"Pdgd": "Partially Degraded",
		"OfLn": "Offline",
		"Rec":  "Recovery",
	}

	if mappedState, ok := stateMap[state]; ok {
		return mappedState
	}

	return state
}

// extractDriveSections 提取驱动器部分，避免使用Go不支持的正则表达式语法
func extractDriveSections(content string) []string {
	// 查找所有 "Drive /c" 开头的位置
	driveStartRegex := regexp.MustCompile(`Drive /c\d+/e\d+/s\d+ :`)
	positions := driveStartRegex.FindAllStringIndex(content, -1)

	if len(positions) == 0 {
		return []string{}
	}

	var sections []string
	for i := 0; i < len(positions); i++ {
		start := positions[i][0]
		end := len(content)
		if i+1 < len(positions) {
			end = positions[i+1][0]
		}

		section := content[start:end]
		sections = append(sections, section)
	}

	return sections
}
